package controller;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ResourceBundle;
import reflection.ReflectionException;

import view.AbstractView;
import view.SwingView;
import model.Model;
import model.Pixmap;

/**
 * A controller used for connecting the model and the view
 * 
 * @author Andrew Patterson
 * @author Charlie Hatcher
 */
public class Controller {
	private ResourceBundle resources = ResourceBundle.getBundle("resources.controllerClasses");
	private static final String LISTENER_REFLECTION_ERROR = "Reflection Error: The Listeners could not be loaded";
	
	private Model myModel;
	private AbstractView myView;

	/**
	 * Creates the Model and the View that the controller will talk to
	 * 
	 * @throws IOException
	 */
	public Controller() throws IOException {
		loadListenersWithController();
		myView = new SwingView();
		myModel = new Model(this);
	}

	/**
	 * Uses reflection to load all the listener classes with this controller
	 */
	private void loadListenersWithController() {
		for (String currentListenerClass : resources.keySet()) {
			try {
				Class.forName(currentListenerClass).getMethod("setController",
						Controller.class).invoke(null, this);
			}
			catch (ClassNotFoundException e) {
				throw new ReflectionException(LISTENER_REFLECTION_ERROR);
			} catch (IllegalArgumentException e) {
				throw new ReflectionException(LISTENER_REFLECTION_ERROR);
			} catch (SecurityException e) {
				throw new ReflectionException(LISTENER_REFLECTION_ERROR);
			} catch (IllegalAccessException e) {
				throw new ReflectionException(LISTENER_REFLECTION_ERROR);
			} catch (InvocationTargetException e) {
				throw new ReflectionException(LISTENER_REFLECTION_ERROR);
			} catch (NoSuchMethodException e) {
				throw new ReflectionException(LISTENER_REFLECTION_ERROR);
			}
		}
	}

	/**
	 * Displays an error message in the view
	 */
	public void displayErrorMessage(String message) {
		myView.displayError(message);
	}

	/**
	 * Displays non-error output to the use
	 */
	public void displayOutput(String output) {
		myView.displayOutput(output);
	}

	/**
	 * Updates the view to display this  pixmap
	 */
	public void updatePixmap(Pixmap pixmap) {
		myView.getCanvas().refresh(pixmap);
	}

	/**
	 * Returns this controller's model
	 */
	protected Model getModel() {
		return myModel;
	}
}